package main

import (
	"bytes"
	"encoding/json"
	"io"
	"net"
	"strings"
)

//start tcp listener
func StartTcpServe() {
	Addr, _ := net.ResolveTCPAddr("tcp4", ":8888")
	listener, err := net.ListenTCP("tcp4", Addr)
	if err != nil {
		log.Error("start tcp listen error > %v", err)
		panic(err)
	}
	log.Info("start tcp listen")
	defer func() {
		log.Info("server is close")
		if err := listener.Close(); err != nil {
			log.Error("listener.Close() error (%v)", err)
		}
	}()
	for {
		conn, err := listener.AcceptTCP()
		log.Info("start accept <%s>", conn.RemoteAddr().String())
		if err != nil {
			log.Error("listener.AcceptTCP() error(%v)", err)
			continue
		}
		go handleTCPConn(conn)
		log.Info("accept finished")
	}
}

func handleTCPConn(conn *net.TCPConn) {
	defer conn.Close()
	addr := conn.RemoteAddr().String()
	log.Info("<%s> handleTCPConn start", addr)
	for {
		data := ReadData(conn)
		if len(data) == 0 {
			//log.Warn("no data recv <%s>", addr)
			return
		}
		go ParseCMD(data, conn)
	}
}

func ReadData(conn net.Conn) []byte {
	var data bytes.Buffer
	var buf [1024]byte
	for {
		n, err := conn.Read(buf[0:])
		if err != nil {
			if err == io.EOF {
				log.Info("recv done")
				//fmt.Println("recv error:" + err.Error())
				break
			} else {
				log.Warn("recv data error <%v>", err)
				return nil
			}
		}
		if buf[n-1] == '\n' {
			data.Write(buf[0 : n-1])
			break
		} else {
			data.Write(buf[0:n])
		}

	}
	return data.Bytes()

}

func SendData(conn net.Conn, data []byte) error {
	data = append(data, '\n')
	_, err := conn.Write(data)
	if err != nil {
		//fmt.Println("send error" + err.Error())
		return err
	}
	return nil
}

func ParseCMD(s []byte, conn net.Conn) {
	var pack map[string]interface{}
	addr := conn.RemoteAddr().String()
	if !bytes.Contains(s, []byte("type")) {
		log.Error("<%s> protol error ", addr)
		return
	}
	if err := json.Unmarshal(s, &pack); err != nil {
		log.Error("<%s %s> data format error,can not unmarshal %v", addr, string(s), err)
		return
	}
	switch pack["type"] {
	//获取client监控项
	case "0":
		ip := strings.Split(conn.RemoteAddr().String(), ":")[0]
		log.Info("<%s> request to get the configuration", ip)
		host := getHostByIP(ip)
		if host != nil {
			data, _ := json.Marshal(host)
			SendData(conn, data)
			log.Info("<%s> send the configuration success", ip)
			return
		}
		SendData(conn, []byte(""))
	//心跳
	case "2":
		log.Info("recv heartbeart")
	//更新客户端version
	case "3":
		log.Info("recv update request")
		var (
			cv string
			nv string
			fn string
		)
		if v, ok := pack["version"].(string); ok {
			cv = v
		}
		c := getClientVersion()
		if c == nil {
			SendData(conn, []byte(""))
			return
		}
		nv = c.Version
		fn = c.Filename
		if cv != nv {
			pk := map[string]interface{}{"version": nv, "filename": fn}
			rep, _ := json.Marshal(pk)
			SendData(conn, rep)
			return
			//2014年8月22日00:53:35
		}
		SendData(conn, []byte(""))
		log.Info("no need to update")
		//上传监控数据
	case "4":
		ParseToTsdb(s)
		SendData(conn,[]byte(""))
	default:
		//log.Warn("<%s> protocol error", addr)
		log.Info("%s",s)
	}
}
